package cn.zyb.basic.service.Impl;

import cn.zyb.basic.contant.VerifyCodeConstant;
import cn.zyb.basic.dto.SmsDto;
import cn.zyb.basic.exception.BusinessException;
import cn.zyb.basic.service.IVerifyService;
import cn.zyb.basic.util.StrUtils;
import cn.zyb.basic.util.VerifyCodeUtils;
import cn.zyb.user.domain.User;
import cn.zyb.user.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @author zyb
 * @version 1.0.0
 * @date 2022年07月14日 16:57:47
 * @packageName cn.zyb.basic.service.Impl
 * @className VerifyServiceImpl
 * @describe TODO
 */
@Service
public class VerifyServiceImpl implements IVerifyService {
  @Autowired
  private RedisTemplate redisTemplate;
  @Autowired
  private UserMapper userMapper;

  @Override
  public String getImgCode(String key) {
    //1.获取随机验证码
    String code = StrUtils.getComplexRandomString(4);
    //2.保存到redis - 并设置5分钟过期
    redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
    //3.获取图形验证码编码的之后的字符串
    String base64Str = VerifyCodeUtils.verifyCode(115, 40, code);
    return base64Str;
  }

  @Override
  public void smsCode(SmsDto smsDto) {
    String phone = smsDto.getPhone();
    String imageCode = smsDto.getImageCode();
    String imageCodeKey = smsDto.getImageCodeKey();
    //1校验
    //1.1.非空校验--3个
    if(StringUtils.isEmpty(phone)){
      throw new BusinessException("手机号码不能为空");
    }
    if(StringUtils.isEmpty(imageCode)){
      throw new BusinessException("请输入图形验证码");
    }
    if(StringUtils.isEmpty(imageCodeKey)){
      throw new BusinessException("重新获取图形验证码");
    }
    //1.2.验证手机号是否被注册过
    User user = userMapper.loadByPhone(phone);
    if(user!=null){
      throw new BusinessException("该手机号已经注册过");
    }
    //1.3.校验图形验证码是否正确
    Object imgObj = redisTemplate.opsForValue().get(imageCodeKey);
    if(imgObj ==null){
      throw new BusinessException("图形验证码过期");
    }
    //1.4.校验图形验证码是否正确
    if(!imgObj.toString().equalsIgnoreCase(imageCode)){
      throw new BusinessException("图形验证码错误");
    }
    //2.生成手机验证码
    //redis保存手机验证码：register:18856566636 - 9527:156336655555
    //2.1.从redis中获取手机验证码 - 进行判断
    Object smsObj = redisTemplate.opsForValue().get(VerifyCodeConstant.REGISTER_CODE_PREFIX + phone); //9527:156336655555
    String smsCode = null;
    if(smsObj == null){
      //2.11如果没有 = 第一次获取或手机验证码过期 -> 重新调用StrUtils创建新的手机验证码
      smsCode = StrUtils.getRandomString(6);
    }else{
      //2.12.如果有 = 手机验证码过期没有过期 -> 判断重发时间【时间戳相减与1分钟】
      long nowTime = System.currentTimeMillis();
      String oldTimeTemp = smsObj.toString().split(":")[1];
      long oldTime = Long.parseLong(oldTimeTemp);
      if((nowTime-oldTime)<1*60*1000){//重复发送短信验证码
        //2.21.如果没有过重发时间 -> 抛业务异常【操作过于频繁，请稍后再试】
        throw new BusinessException("操作过于频繁，请稍后再试");
      }else{
        //2.22.如果过了重发时间 -> 就使用以前的验证码
        smsCode = smsObj.toString().split(":")[0];
      }
    }
    //3.手机验证码保存到redis - 要不要刷新过期时间？[保存到redis要不要再次设置3分钟有效]
    redisTemplate.opsForValue().set(VerifyCodeConstant.REGISTER_CODE_PREFIX +phone,
      smsCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);

    //4.调用工具类发送短信
    //SmsUtils.sendSms(phone,"你的验证码是：" + smsCode+",请在3分钟内使用!!!");
    System.out.println("你的验证码是：" + smsCode+",请在3分钟内使用!!!");
  }
  @Override
  public void binderSmsCode(SmsDto smsDto) {
    String phone = smsDto.getPhone();
    //1.校验
    //a.非空校验 - 3个
    if(StringUtils.isEmpty(phone)){
      throw new BusinessException("手机号码不能为空");
    }
    //2.生成手机验证码
    //redis保存手机验证码：register:18856566636 - 9527:156336655555
    //a.从redis中获取手机验证码 - 进行判断
    Object smsObj = redisTemplate.opsForValue().get(VerifyCodeConstant.BINDER_CODE_PREFIX + phone); //9527:156336655555
    String smsCode = null;
    if(smsObj == null){
      //a1.如果没有 = 第一次获取或手机验证码过期 -> 重新调用StrUtils创建新的手机验证码
      smsCode = StrUtils.getRandomString(6);
    }else{
      //a2.如果有 = 手机验证码过期没有过期 -> 判断重发时间【时间戳相减与1分钟】
      long nowTime = System.currentTimeMillis();
      String oldTimeTemp = smsObj.toString().split(":")[1];
      long oldTime = Long.parseLong(oldTimeTemp);
      if((nowTime-oldTime)<1*60*1000){//重复发送短信验证码
        //a21.如果没有过重发时间 -> 抛业务异常【操作过于频繁，请稍后再试】
        throw new BusinessException("操作过于频繁，请稍后再试");
      }else{
        //a22.如果过了重发时间 -> 就使用以前的验证码
        smsCode = smsObj.toString().split(":")[0];
      }
    }
    //3.手机验证码保存到redis - 要不要刷新过期时间？[保存到redis要不要再次设置3分钟有效]
    redisTemplate.opsForValue().set(VerifyCodeConstant.BINDER_CODE_PREFIX+phone,
      smsCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);
    //4.调用工具类发送短信
    //SmsUtils.sendSms(phone,"你的验证码是：" + smsCode+",请在3分钟内使用!!!");
    System.out.println("你的验证码是：" + smsCode+",请在3分钟内使用!!!");
  }
}
